package com.shuyun.concurrent;

import cn.hutool.core.date.DateUtil;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

/**
 * @description: https://www.cnblogs.com/huhx/p/baseusejavaScheduledExecutorService.html
 * @author: shuai.chen@shuyun.com
 * @date: 2022/9/29 1:43 PM
 */
public class ScheduledExecutorServiceDemo {

    public static void main(String[] args) {
        demo02();
    }

    public static void demo01() {
        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleAtFixedRate(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(DateUtil.formatDateTime(new Date()) + " run ...");
        }, 0, 2, TimeUnit.SECONDS);
    }

    public static void demo02() {
        try {
            List<Callable> callableList = new ArrayList<>();
            callableList.add(new SendToken());
            ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
            ScheduledFuture futureA = executorService.schedule(callableList.get(0), 2L, TimeUnit.SECONDS);

            System.out.println("接到请求后，刷新token到库, time: " + DateUtil.formatDateTime(new Date()));
            System.out.println("接收合作伙伴的响应: " + futureA.get());
            System.out.println("推送token给客户, time: " + DateUtil.formatDateTime(new Date()));

            executorService.shutdown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    public static void demo03() {
        try {
            List<Callable> callableList = new ArrayList<>();
            callableList.add(new MyCallableA());
            callableList.add(new MyCallableB());
            ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
            ScheduledFuture futureA = executorService.schedule(callableList.get(0), 4L, TimeUnit.SECONDS);
            ScheduledFuture futureB = executorService.schedule(callableList.get(1), 4L, TimeUnit.SECONDS);

            System.out.println("            X = " + DateUtil.formatDateTime(new Date()));
            System.out.println("返回值A：" + futureA.get());
            System.out.println("返回值B：" + futureB.get());
            System.out.println("            Y = " + DateUtil.formatDateTime(new Date()));

            executorService.shutdown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    static class SendToken implements Callable<String> {
        @Override
        public String call() throws Exception {
            try {
                System.out.println("给合作伙伴发送token: " + Thread.currentThread().getName() + ", " + DateUtil.formatDateTime(new Date()));
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "returnA";
        }
    }

    static class MyCallableA implements Callable<String> {
        @Override
        public String call() throws Exception{
            try {
                System.out.println("callA begin " + Thread.currentThread().getName() + ", " + DateUtil.formatDateTime(new Date()));
                // 休眠3秒
                TimeUnit.SECONDS.sleep(3);
                System.out.println("callA end " + Thread.currentThread().getName() + ", " + DateUtil.formatDateTime(new Date()));
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "returnA";
        }
    }

    static class MyCallableB implements Callable<String>  {
        @Override
        public String call() throws Exception{
            System.out.println("callB begin " + Thread.currentThread().getName() + ", " + System.currentTimeMillis());
            System.out.println("callB end " + Thread.currentThread().getName() + ", " + System.currentTimeMillis());
            return "returnB";
        }
    }

}
